#include "CCD.h"

int16 hCam;
uns16 frame[512*512];
uns16 sts[65536];
void check_err(lua_State * L,rs_bool pl_return)
{
	static char msg[ERROR_MSG_LEN];
	if(!pl_return){pl_error_message(pl_error_code(),msg);luaL_error(L,"%s",msg);}
}

static void SetWorkingSpeed(int16 hCam);

int main();

int luaopen_CCD(lua_State * L)
{
	luaL_reg lib_CCD[]=
	{
		{"open",&ccd_open},
		{"setexp",&ccd_set_exp},
		{"exp",&ccd_exp},
		{"status",&ccd_status},
		{"getdata",&ccd_get_data},
		{"close",&ccd_close},
		{NULL,NULL},
	};
	luaL_register(L,"CCD",lib_CCD);
	return 0;
}
/*
static int ccd_open(lua_State * L);
static int ccd_set_exp(lua_State * L);
static int ccd_set_temp(lua_State * L);
static int ccd_exp(lua_State * L);
static int ccd_status(lua_State * L);
static int ccd_get_temp(lua_State * L);
static int ccd_close(lua_State * L);
*/

int ccd_open(lua_State * L)
{
	char cam_name[CAM_NAME_LEN];
	int16 speed=0;
	uns16 exp_res_idx=1;
	check_err(L,pl_pvcam_init());
	check_err(L,pl_cam_get_name(0,cam_name));
	check_err(L,pl_cam_open(cam_name,&hCam,OPEN_EXCLUSIVE));
	check_err(L,pl_set_param(hCam,PARAM_SPDTAB_INDEX,&speed));
	check_err(L,pl_set_param(hCam,PARAM_EXP_RES_INDEX,&exp_res_idx));
	check_err(L,pl_exp_init_seq());
	return 0;
}

int ccd_set_exp(lua_State * L)
{
	uns16 s1=(uns16)luaL_checkint(L,1);
	uns16 s2=(uns16)luaL_checkint(L,2);
	uns16 p1=(uns16)luaL_checkint(L,3);
	uns16 p2=(uns16)luaL_checkint(L,4);
	rgn_type region={s1,s2,1,p1,p2,1};
	uns32 exp_time=(uns32)luaL_checkint(L,5);
	uns32 size;
	check_err(L,pl_exp_setup_seq(hCam,1,1,&region,TIMED_MODE,exp_time,&size));
	lua_pushnumber(L,size);
	return 1;
}

int ccd_exp(lua_State * L)
{
	check_err(L,pl_exp_start_seq(hCam,frame));
	return 0;
}

int ccd_status(lua_State * L)
{
	static int16 status;
	static uns32 not_needed;
	check_err(L,pl_exp_check_status(hCam,&status,&not_needed));
	lua_pushnumber(L,status);
	return 1;
}

int ccd_get_data(lua_State * L)
{
	byte * img=(byte *)lua_touserdata(L,1);
	uns16 w=luaL_checkint(L,2);
	uns16 h=luaL_checkint(L,3);
	int i,j;
	uns16 minv=65535;
	uns16 maxv=0;
	uns16 range,halfmax;
	uns32 avg=0;
	uns32 point=0;
	uns32 point_n=0;
	uns32 point_x=0;
	uns32 point_y=0;
	if(!img) luaL_error(L,"Invalid image data pointer.");
	for(i=0;i<w*h;i++)
	{
		maxv=max(frame[i],maxv);
		minv=min(frame[i],minv);
		avg+=(frame[i]/256);
	}
	avg=(uns32)(avg*256.0/w/h);
	range=maxv-minv;
	halfmax=(maxv-minv)/2+minv;
	for(i=0;i<w;i++)
		for(j=0;j<h;j++)
			if(frame[i+j*w]>halfmax)
			{
				point_n++;
				point+=frame[i+j*w]/16;
				point_x+=i;
				point_y+=j;
			}
	for(i=0;i<w;i++)
		for(j=0;j<h;j++)
		{
			img[(i+j*w)*3]=img[(i+j*w)*3+1]=img[(i+j*w)*3+2]=(frame[i+j*w]-minv)*255/range;
		}
	lua_pushnumber(L,minv);
	lua_pushnumber(L,maxv);
	lua_pushnumber(L,range);
	lua_pushnumber(L,avg);
	lua_pushnumber(L,point_n);
	lua_pushnumber(L,point);
	lua_pushnumber(L,point_x/point_n);
	lua_pushnumber(L,point_y/point_n);
	return 8;
}

int ccd_close(lua_State * L)
{
	check_err(L,pl_exp_uninit_seq());
	check_err(L,pl_cam_close(hCam));
	check_err(L,pl_pvcam_uninit());
	return 0;
}

void SetWorkingTemperature(int16 hCam,int workingtemperature)
{

    rs_bool status;
    int16 tmp_hi;/*For save the highest temperature could be set for CCD*/
    int16 tmp_lo;/*For save the lowest temperature could be set for CCD*/
	int16 SetTemperature;
	int16 tmp_cur;
	/*Get the temperature range could be set for CCD*/
    pl_ccd_get_tmp_range(hCam, &tmp_hi, &tmp_lo );

	/*All the temperature in CCD is 100 times to it's true value*/
	SetTemperature = 100*workingtemperature;                              
    if((SetTemperature<=tmp_hi)&&(SetTemperature>=tmp_lo))
   {
          status=pl_ccd_set_tmp_setpoint( hCam, SetTemperature );/*Set the temperature*/
		  //also can use pl_set_param( hCam, PARAM_TEMP_SETPOINT, (void*)&SetTemperature));
    }
    else if(SetTemperature<tmp_lo)
         {  SetTemperature=tmp_lo;
            status=pl_ccd_set_tmp_setpoint( hCam, SetTemperature ); }
         else
         {  SetTemperature=tmp_hi;
            status=pl_ccd_set_tmp_setpoint( hCam, SetTemperature ); }
    if(status)
    {
	printf("Set Temperature Success. \n");}
    else
    {printf("Set Temperature Error. \n");}
	pl_ccd_get_tmp(hCam,&tmp_cur);
	printf("Current T=%f\n",tmp_cur/100.0);
}
